package com.tb.sng.utils.bmp
{
	/**
	 * BitmapMovieClip 将矢量图或其他格式的movieclip初始化为
	 * athor:hanbing01
	 *
	 */
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.FrameLabel;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.events.ErrorEvent;
	import flash.events.Event;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.Dictionary;
	
	public class BitmapMovieClip extends Sprite
	{
		/**
		 * 该对象的对象池
		 */		
		private static var _const_id:int = 0;
		
		/**
		 * 所有类型的显示对象池，key为movieclip的类型,value为一个Vector.<BitMapData>的该帧的动画序列
		 */		
		private static var ClassBitmapDataLoop:Dictionary = new Dictionary();
		
		/**
		 * 所有类型的显示对象位置池，key为MovieClip的类型，value为一个Vector.<Point>的该帧的位置。
		 */		
		private static var ClassPosLoop:Dictionary = new Dictionary();
		/**
		 * 所有bitmapClip对象的对象池 
		 */		
		private static var ObjectLoop:Dictionary = new Dictionary(true);
		
		
		/**
		 * 是否被初始化完成 
		 */		
		private static var _needinstalled:Boolean = true;
		
		/**
		 * 将该位图动画剪辑应用到场景中,只需执行一次
		 * @param stage
		 * 
		 */		
		public static function install(_stage:Stage):void
		{
			if(_stage&&_needinstalled)
			{
				_stage.addEventListener(Event.ENTER_FRAME,enterFrame);
				_stage.addEventListener(Event.EXIT_FRAME,exitFrame);
				_needinstalled= false;
			}
		}
		/**
		 * 进入帧事件
		 * @param e
		 * 
		 */		
		private static function enterFrame(e:Event):void
		{
			for each(var obj:BitmapMovieClip in ObjectLoop)
			{
				obj.showFrame();
			}
		}
		
		/**
		 * 退出帧事件 
		 * @param e
		 * 
		 */		
		private static function exitFrame(e:Event):void
		{
			for each(var obj:BitmapMovieClip in ObjectLoop)
			{
				obj.exitFrame();
			}
		}
		public static function uninstall():void
		{
			//TODO: 从类型池中释放某个class
		}
		
		/**
		 * 对应的动画资源 
		 */		
		private var _bitmap_vec:Vector.<BitmapData>;
		
		/**
		 * 对应位图应该所在的位置 
		 */		
		private var _pos_vec:Vector.<Point>;
		
		/**
		 * 位图可显示对象 
		 */		
		private var _bitmap:Bitmap;

		/**
		 *  牛逼的构造函数 
		 * @param cl 需要生成位图movieclip的movieclip类
		 * @param scaleX 需要缩放的X
		 * @param scaleY 需要缩放的Y
		 * 
		 */
		public function BitmapMovieClip(cl:Class,tscaleX:Number = 1.0,tscaleY:Number = 1.0)
		{
			super();
			//TODO: 构造labels 数组
			try{
				var mc:MovieClip = new cl();
			}catch(e:Error)
			{
				trace("Please use a MovieClip Class");
				return;
			}
			var arr_labels:Array = mc.currentLabels;
			_currentLabels = new Dictionary();
			_bitmap = new Bitmap(null,"auto",true);
			addChild(_bitmap);
			for each(var label:FrameLabel in arr_labels)
			{
				_currentLabels[label.frame] = new FrameLabel(label.name,label.frame);
			}
			_totalFrames = mc.totalFrames;
			if(ClassBitmapDataLoop[cl] == null)
			{
				//TODO: 处理并生成所有动画帧
				mc.scaleX = tscaleX;
				mc.scaleY = tscaleY;
				var bitmap_vec:Vector.<BitmapData> = new Vector.<BitmapData>(_totalFrames+1);
				var pos_vec:Vector.<Point> = new Vector.<Point>(_totalFrames+1);
				var frame_num:int =1;
				var _mx:Matrix;
				var _rect:Rectangle;
				while(frame_num<=_totalFrames)
				{
					mc.gotoAndStop(frame_num);
					bitmap_vec[frame_num] = new BitmapData(mc.width,mc.height,true,0x0);
					_mx = new Matrix();
					_rect = mc.getBounds(mc);
					_mx.createBox(mc.scaleX,mc.scaleY,0,-_rect.left * mc.scaleX,-_rect.top * mc.scaleY);
					
					bitmap_vec[frame_num].draw(mc,_mx);
					pos_vec[frame_num] = new Point(_rect.left * mc.scaleX,_rect.top * mc.scaleY);
					frame_num++;
				}
				ClassBitmapDataLoop[cl] = bitmap_vec;
				ClassPosLoop[cl] = pos_vec;
			}
			_bitmap_vec = ClassBitmapDataLoop[cl];
			_pos_vec = ClassPosLoop[cl];
			_id = _const_id;
			_installListener();
			_currentFrame = 1;
			_stop = false;
			_const_id ++;
		}
		
		public function _installListener():void
		{
			if (stage)
				init();
			else
				addEventListener(Event.ADDED_TO_STAGE, init);
			addEventListener(Event.REMOVED_FROM_STAGE,removeHandler);
		}
		
		/**
		 * 进入场景初始化函数 
		 * @param e
		 * 
		 */		
		private function init(e:Event = null):void
		{
			removeEventListener(Event.ADDED_TO_STAGE,init);
			
			ObjectLoop[_id] = this;
		}
		/**
		 * 移除该可显示对象 
		 * 
		 */		
		private function removeHandler(e:Event):void
		{
			removeEventListener(Event.REMOVED_FROM_STAGE,removeHandler);
			delete ObjectLoop[_id];
		}
		//		public static function createBitmapMovieClip(cl:Class):void
		//		{
		//			
		//		}
		
		/**
		 * 该数据在对象池中的id 
		 */		
		private var _id:int;
		/**
		 * 当前帧编号
		 */		
		private var _currentFrame:int;
		/**
		 * [只读] currentFrame:int  
		 * 指定播放头在 MovieClip 实例的时间轴中所处的帧的编号。 
		 * 如果影片剪辑有多个场景，该值是当前场景中的帧编号。
		 * 
		 */		
		public function get currentFrame():int
		{
			return _currentFrame;
		}
		
		/**
		 * [只读] currentFrameLabel
		 * MovieClip 实例的时间轴中当前帧上的标签。如果当前帧没有标签，则 currentLabel 为 null。
		 * 
		 */		
		public function get currentFrameLabel():String
		{	
			return _currentLabels[_currentFrame]?(_currentLabels[_currentFrame] as FrameLabel).name:"";
		}
		
		
		/**
		 * [只读] currentLabel
		 * 在 MovieClip 实例的时间轴中播放头所在的当前标签。 
		 * 
		 */		
		public function get currentLabel():String
		{
			var frame:int = _currentFrame;
			while(frame&&(_currentLabels[frame]==null))
			{
				frame --;
			}
			return frame==0?"":(_currentLabels[_currentFrame] as FrameLabel).name;
		}
		
		
		/**
		 * 帧标签列表 
		 */		
		private var _currentLabels:Dictionary;
		/**
		 * 返回由当前场景的 FrameLabel 对象组成的数组。 如果 MovieClip 实例不使用场景，数组会包括整个 MovieClip 实例的所有帧标签。 
		 * 
		 * 
		 */		
		public function get currentLabels():Array
		{
			var arr:Array = [];
			for each(var label:FrameLabel in _currentLabels)
			{
				arr.push(label);
			}
			return arr;
		}
		
		/**
		 * 根据当前帧以及状态播放该影片剪辑，并派发enterframe事件
		 * 
		 */		
		private function showFrame():void
		{
			if(stage==null)
				return;
			_bitmap.bitmapData = _bitmap_vec[_currentFrame];
			_bitmap.x = _pos_vec[_currentFrame].x;
			_bitmap.y = _pos_vec[_currentFrame].y;
			this.dispatchEvent(new Event(Event.ENTER_FRAME));
		}
		/**
		 * 离开该影片剪辑
		 * 
		 */		
		private function exitFrame():void
		{
			if(stage==null)
				return;
			if(_stop)
			{
				//保持状态不派发事件
			}else
			{
				//若播放到头则，执行
				if(_currentFrame==totalFrames)
					_currentFrame = 1;
				else
					_currentFrame++;
				this.dispatchEvent(new Event(Event.EXIT_FRAME));
			}
		}
		
		/**
		 * 该影片是否停止状态，若为true 则不会在show之后进入下一帧，否则进入下一帧 
		 */		
		private var _stop:Boolean;
		
		/**
		 * 停止影片剪辑中的播放头。 不会重新播放，使用play之后继续播放
		 * 
		 */		
		public function stop():void
		{
			this._stop = true;
		}
		
		/**
		 * 在影片剪辑的时间轴中移动播放头。 
		 * 
		 */		
		public function play():void
		{
			this._stop = false;
		}
		
		/**
		 * 总帧数 需统计
		 * 
		 */
		private var _totalFrames:int;
		
		/**
		 * 如果影片剪辑包含多个帧，totalFrames 属性会返回影片剪辑中的所有 场景中的帧的总数。 
		 * 
		 */
		public function get totalFrames():int
		{
			return _totalFrames;
		}
		
		/**
		 * gotoAndPlay
		 * 从指定帧开始播放 SWF 文件。  不支持多场景
		 * 
		 */
		public function gotoAndPlay(frame:Object):void
		{
			_stop = false;
			//说明为帧数
			if(frame is String)
			{
				for each(var label:FrameLabel in _currentLabels)
				{	
					if(frame == label.name)
					{
						_currentFrame = label.frame;
						return;
					}
					_currentFrame = 1;
				}
			}else
			{
				if(frame<=0)
				{
					frame = 1;
				}else if(frame>_totalFrames)
				{
					frame = _totalFrames;
				}
				_currentFrame = int(frame);
			}
			
		}
		
		
		/**
		 * gotoAndStop
		 * 从指定帧开始播放 SWF 文件。  不支持多场景
		 * 
		 */
		public function gotoAndStop(frame:Object):void
		{
			_stop = true;
			//说明为帧数
			if(frame is String)
			{
				for each(var label:FrameLabel in _currentLabels)
				{
					if(frame == label.name)
					{
						_currentFrame = label.frame;
						return;
					}
				}
				_currentFrame = 1;
			}else
			{
				if(frame<=0)
				{
					frame = 1;
				}else if(frame>_totalFrames)
				{
					frame = _totalFrames;
				}
				_currentFrame = int(frame);
			}
			
		}
		/**
		 * 将播放头转到前一帧并停止。 这会在帧中的所有剩余动作执行完毕后发生。  
		 * 
		 */		
		public function prevFrame():void
		{
			_stop = true;
			_currentFrame --;
			if(_currentFrame<1)
			{
				_currentFrame = 1;
			}
		}
		
		/**
		 * 将播放头转到下一帧并停止。 这会在帧中的所有剩余动作执行完毕后发生。 
		 * 
		 */		
		public function nextFrame():void
		{
			_stop = true;
			_currentFrame ++;
			if(_currentFrame>_totalFrames)
			{
				_currentFrame = _totalFrames;
			}
		}
		
		
		
		
	}
}